package cn.linstudy.web.controller;

import cn.linstudy.common.domain.UserInfo;
import cn.linstudy.common.exception.BusinessException;
import cn.linstudy.common.web.Result;
import cn.linstudy.common.web.anno.RequireLogin;
import cn.linstudy.domain.SeckillProductVo;
import cn.linstudy.mq.MQConstant;
import cn.linstudy.mq.OrderMessage;
import cn.linstudy.redis.SeckillRedisKey;
import cn.linstudy.service.IOrderInfoService;
import cn.linstudy.service.ISeckillProductService;
import cn.linstudy.util.DateUtil;
import cn.linstudy.util.UserUtil;
import cn.linstudy.web.msg.SeckillCodeMsg;
import java.sql.ResultSet;
import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;
import javax.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


@RestController
@RequestMapping("/order")
@Slf4j
public class OrderInfoController {
    @Autowired
    private ISeckillProductService seckillProductService;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Autowired
    private IOrderInfoService orderInfoService;
    // 用来减少redis的压力，做一个本地标识，key为秒杀商品id，value为boolean，当库存1小于1的时候就设置为true
    public static final ConcurrentHashMap<Long,Boolean> local_flag = new ConcurrentHashMap<>();

    @RequestMapping("/doSeckill")
    @RequireLogin
    public Result<String> doSeckill(String seckillId,String time, HttpServletRequest request){
        // 1. 判断是否登录(拦截器已经写了)
        // 2. 对参数进行校验
        if (StringUtils.isEmpty(seckillId) || StringUtils.isEmpty(time)){
            throw new  BusinessException(SeckillCodeMsg.PARM_IS_EMPTY);
        }
        // 3. 判断它是否在活动期内
        SeckillProductVo productVo = seckillProductService
            .find(Integer.parseInt(time), Long.parseLong(seckillId)).getData();
        boolean legalTime = DateUtil.isLegalTime(productVo.getStartDate(), Integer.parseInt(time));
        // 不在活动期内(为了测试方便注释掉)
//        if (!legalTime){
//            throw new BusinessException(SeckillCodeMsg.OUT_TIME);
//        }
        // 根据boolean值判断库存是否足够
        Boolean local_flag = OrderInfoController.local_flag.get(seckillId);
        if (local_flag!= null && local_flag){
            throw new BusinessException(SeckillCodeMsg.SECKILL_STOCK_OVER);
        }
        // 利用redis控制认数
        redisTemplate.opsForHash().increment(SeckillRedisKey.SECKILL_ORDER_HASH.getRealKey(time+""), seckillId+"",-1);
        // 4. 判断库存是否足够
        if (productVo.getStockCount() <= 0){
            OrderInfoController.local_flag.put(Long.parseLong(seckillId),true);
            throw new BusinessException(SeckillCodeMsg.SECKILL_STOCK_OVER);
        }
        // 5. 判断用户是否重复下单,使用set：key 用户电话：秒杀商品id
        // isMember 表示的是判断这个key是否在redis里面
        UserInfo userInfo = UserUtil.getUser(redisTemplate, request.getHeader("token"));
        Boolean is_buy = redisTemplate.opsForSet()
            .isMember(SeckillRedisKey.SECKILL_ORDER_SET.getRealKey(time),
                userInfo.getPhone() + ":" + seckillId);
        // 如果为true，表示已经下过单了
        if (is_buy){
            throw new BusinessException(SeckillCodeMsg.REPEAT_SECKILL);
        }

        OrderMessage orderMessage = new OrderMessage();
        orderMessage.setSeckillId(Long.parseLong(seckillId));
        orderMessage.setTime(Integer.parseInt(time));
        orderMessage.setToken(request.getHeader("token"));
        orderMessage.setUserPhone(userInfo.getPhone());
        // 利用MQ去发消息
        rocketMQTemplate.syncSend(MQConstant.ORDER_PEDDING_TOPIC,orderMessage);
        // 6. 真正执行秒杀业务逻辑
       return Result.success("正在申购中，请稍等");
    }
}
